﻿/* Rick van Bodegraven - 0915335
 * 0915335bodegraven@hszuyd.nl
 * 
 * 11-10-2010 - Versie 0.1
 * 13-10-2010 - Versie 0.2 
 * 14-10-2010 - Versie 0.3
 * 15-10-2010 - Versie 0.4
 * 
 * De controller van de  MVC. Hiermee wordt bijvoorbeeld het Model geupdate.
 *
 * subscribed naar alle gui-events
 * per kaart die neergelegd wordt -> event
 * power down -> event
 */

using Roborally.Bord;
using Roborally.CommonData.GlobaleTypes;
using Roborally.Spelleider;
using Roborally.CommonData.Enums;
using System.Collections.Generic;
using System;

namespace Roborally.Server
{
    /// <summary>
    /// De klasse controller, handelt alle communicatie met de GUI af, op een of andere manier met een nog te implementeren Transceiver klasse.
    /// </summary>
    public class Controller : IController
    {
        #region Property's & Fields
        private IModel model;
        private List<IView> views;
        private Spelleider.Spelleider spelleider;
        private List<int> SpelerIDs;
        #endregion

        /// <summary>
        /// TESSSSST
        /// </summary>
        public Spelleider.Spelleider Spelleider
        {
            get { return spelleider; }
        }

        /// <summary>
        /// De Constructor van Controller
        /// Deze geeft elke speler een view, maakt een spelleider aan voor het spel en een model
        /// </summary>
        /// <param name="gekozenBord">Het gekozen bord waarop wordt gespeeld in een spel</param>
        /// <param name="info">De nieuwe info die gebruikt wordt voor het spel</param>
        public Controller(IBord gekozenBord, NieuwSpelGegevens info)
        {
            List<ModelSpelerInfo> modelSpelerInfo = new List<ModelSpelerInfo>();
            foreach (var item in info.SpelerIDEnNaam)
            {
                modelSpelerInfo.Add(new ModelSpelerInfo(item.Key, item.Value, info.DicIDRobotType[item.Key]));
            }

            model = new Model(gekozenBord, modelSpelerInfo);
            //SpelInformatie spelInfo = new SpelInformatie(info.APIray, info.SpelerIDEnNaam, model);
            int[] aantalais = {};
            SpelInformatie spelInfo = new SpelInformatie(aantalais, info.SpelerIDEnNaam, model);
            spelleider = new Spelleider.Spelleider(spelInfo);

            spelleider.DeelKaartenEvent += new DeelKaartenEventHandler(spelleider_DeelKaarten);
            spelleider.VerplaatsAlleSpelers += new VerplaatsAlleSpelersEventHandler(Spelleider_VerplaatsAlleSpelers);
            spelleider.SpelGewonnen += new SpelGewonnenEventHandeler(spelleider_SpelGewonnen);

            SpelerIDs = new List<int>();
            foreach (KeyValuePair<int, string> item in info.SpelerIDEnNaam)
            {
                SpelerIDs.Add(item.Key);
            }

            views = new List<IView>();
            for (int i = 0; i < SpelerIDs.Count; i++)
            {
                views.Add(new View(SpelerIDs[i], model));
            }
        }

        void spelleider_SpelGewonnen(int winnaarId)
        {
            Console.WriteLine("Spel gewonnen!");
            string winnaarInfo = "";
            for (int i = 0; i < model.ModelSpelerInfos.Count; i++)
            {
                if (winnaarId == model.ModelSpelerInfos[i].SpelerID)
                    winnaarInfo = model.ModelSpelerInfos[i].ToTransferString();
            }
            foreach (var view in views)
            {
                view.EindeSpel(winnaarInfo);
            }
        }

        /// <summary>
        /// Event handler uitdelen van kaarten vanuit spelleider
        /// </summary>
        /// <param name="args"></param>
        private void spelleider_DeelKaarten(SpelerIDsEnKaarten args)
        {
            foreach (var spelerKaarten in args.KaartenVanSpelers)
            {
                foreach (var view in views)
                {
                    if (spelerKaarten.Key == view.SpelerID)
                    {
                        view.DeelKaarten(spelerKaarten.Value);
                    }
                }
            }
        }

        /// <summary>
        /// Event om de spelleider te melden dat de spelers verplaats worden
        /// </summary>
        /// <param name="args">alle informatie </param>
        /// <remarks>public ipv private ivm testen</remarks>
        public void Spelleider_VerplaatsAlleSpelers(SpelerLocaties args)
        {
            for (int i = 0; i < model.ModelSpelerInfos.Count; i++)
            {
                for (int j = 0; j < args.AlleGegevens.Count; j++)
                {
                    if (model.ModelSpelerInfos[i].SpelerID == args.AlleGegevens[j].SpelersID)
                    {
                        if (args.AlleGegevens[i].NieuweLocatie != args.AlleGegevens[j].OudeLocatie)
                        {
                            model.ModelSpelerInfos[i].VeranderLocatie(args.AlleGegevens[j].NieuweLocatie);
                        }

                        model.ModelSpelerInfos[i].Richting = args.AlleGegevens[j].RichtingSpeler;
                        model.ModelSpelerInfos[i].Schade = args.AlleGegevens[j].Schade;
                        model.ModelSpelerInfos[i].Levens = args.AlleGegevens[j].Levens;
                        model.ModelSpelerInfos[i].PowerDown = args.AlleGegevens[j].Powerdown;
                        //TODO: FIX in overleg met spelleider
                        //model.ModelSpelerInfos[i].Checkpoints = args.AlleGegevens[j].Checkpoints;
                        //model.ModelSpelerInfos[i].GelockteBaaien = args.AlleGegevens[j].GelockteBaaien; //optioneel (27-10-2010)
                        model.ModelSpelerInfos[i].ProgrammeerBaai = args.AlleGegevens[j].GekozenKaarten;
                        model.ModelSpelerInfos[i].KaartIndex = args.AlleGegevens[j].KaartIndex;
                    }
                }
            }

            if (model is Model)
                ((Model)model).UpdateModel();
            // else throw exception
        }

        /// <summary>
        /// Deze methode zet een speler op Powerdown of controleert een kaart van een speler
        /// </summary>
        /// <param name="spelerID">Het spelerID</param>
        /// <param name="info">slotIndex, ProgramKaart: KaartSoort, aantalStappen, Prioriteit in een string</param>
        /// <returns></returns>
        public bool UpdateSpelSituatie(int spelerID, string info)
        {
            SpelerLegtKaartenArgs data;
            ProgramKaart kaart;
            KaartSoort soort;
            int aantalStappen;
            int prioritiet;
            int slotNummer;
            string temp;

            string identifier = info.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[0];
            info = info.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries)[1];
            switch (identifier)
            {
                case "Powerdown":
                    break;
                case "SpelerLegtKaartNeer":
                    temp = info.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)[0];
                    slotNummer = Convert.ToInt32(temp);
                    temp = info.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)[1];
                    soort = (KaartSoort)Convert.ToInt32(temp);
                    temp = info.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)[2];
                    aantalStappen = Convert.ToInt32(temp);
                    temp = info.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)[3];
                    prioritiet = Convert.ToInt32(temp);
                    kaart = new ProgramKaart(soort, prioritiet, aantalStappen);
                    data = new SpelerLegtKaartenArgs(spelerID, kaart, slotNummer);
                    spelleider.SpelerLegtKaartenNeer(data);
                    break;
            }
            return true;
        }

    }
}